#include "NUC123Series.h"
#include "contiki.h"

#define SR04_TRIGGER_HIGH()		GPIO_SET_PIN(PB13)
#define SR04_TRIGGER_LOW()		GPIO_CLR_PIN(PB13)

#define SR04_NONE		0
#define SR04_TRIGGER	1
#define SR04_WAIT		2
#define SR04_FINISH		3

static uint8_t u8Sr04State;
static unsigned long long  u64Time;

void EINT0_IRQHandler(void)
{
	switch(u8Sr04State)
	{
		case SR04_TRIGGER:
			u64Time = clock_usec();
			u8Sr04State = SR04_WAIT;			
			break;
		case SR04_WAIT:
			u64Time = clock_usec()-u64Time;
			u8Sr04State = SR04_FINISH;			
			break;
		default:
			break;
	}
}

void Sr04_init(void)
{
	GPIO_SET_MODE(PB, 14, GPIO_QUASI);   //En:Configure PB.14 as quasi-bidirection mode
	NVIC_EnableIRQ(EINT0_IRQn);                  //En:Enable NVIC EINT0_IRQn interrupt

	GPIO_SET_DEBOUNCE_TIME(GPIO_DBCLKSRC_HCLK, GPIO_DBCLKSEL_256); //En:Set interrupt pin PD.0 debounce time	
	GPIO_ENABLE_DEBOUNCE(PB, 14);                //En:Enable PD.0 debounce function

	GPIO_SET_MODE(PB, 13, GPIO_OUTPUT); 
	SR04_TRIGGER_LOW();
	u8Sr04State = SR04_NONE;
}

void Sr04_StartTrigger(void)
{
	u8Sr04State = SR04_TRIGGER;
	GPIO_EnableInt(PB, 14, GPIO_INT_BOTH_EDGE);  //En:Set PB.14 to EINT0 function and set both falling and rising edge type of interrupt
	SR04_TRIGGER_HIGH();
	clock_delay_usec(50);
	SR04_TRIGGER_LOW();
}

void Sr04_StopTrigger(void)
{
	DrvGPIO_DisableEINT0();
	u8Sr04State = SR04_NONE;
}

int32_t Sr04_GetDistance(uint16_t u16Timeout)
{
	uint32_t u32Time;
	if(u8Sr04State != SR04_NONE)
	{
		u32Time = clock_time();
		while(u8Sr04State != SR04_FINISH)
		{
			if(clock_diff(u32Time) >  u16Timeout)
			{
				Sr04_StopTrigger();
				return -1;
			}
		}

		return u64Time/58;		// unit cm, 340/s u64Time/2/1000000*340*100 = u64Time/58
	}

	return -1;
}


